<template>
  <div class="menu-manage p-4" tabindex="0">
    <!-- 操作按钮区域 -->
    <div class="mb-4 flex flex-wrap gap-2 items-center">
      <el-input
        v-model="queryParams.menuName"
        placeholder="请输入菜单信息"
        style="width: 200px"
        clearable
        @keyup.enter="handleSearch"
        @clear="handleSearch"
      >
        <template #prefix>
          <el-icon><Search /></el-icon>
        </template>
      </el-input>
      <el-button type="primary" @click="handleAdd" ref="addButton">
        <el-icon><Plus /></el-icon>
        新增
      </el-button>
      <el-button type="primary" plain @click="handleSearch">
        <el-icon><Search /></el-icon>
        查询
      </el-button>
      <el-button type="info" plain @click="handleReset">
        <el-icon><Refresh /></el-icon>
        重置
      </el-button>
    </div>

    <!-- 表格 -->
    <el-table
      v-loading="loading"
      :data="tableData"
      border
      row-key="id"
      default-expand-all
    >
      <el-table-column prop="menuName" label="菜单名称" min-width="150" />
      <el-table-column prop="orderNum" label="排序" width="80" align="center" />
      <el-table-column label="图标" width="80" align="center">
        <template #default="scope">
          <el-icon v-if="scope.row.icon">
            <component :is="scope.row.icon" />
          </el-icon>
        </template>
      </el-table-column>
      <el-table-column prop="path" label="路由" min-width="150" />
      <el-table-column prop="component" label="组件路径" min-width="150" />
      <el-table-column prop="menuType" label="菜单类型" width="120">
        <template #default="scope">
          <el-tag v-if="scope.row.menuType === 'M'">目录</el-tag>
          <el-tag v-else-if="scope.row.menuType === 'F'" type="success"
            >菜单</el-tag
          >
          <el-tag v-else-if="scope.row.menuType === 'O'" type="info"
            >接口</el-tag
          >
          <el-tag v-else type="info">未知</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="visible" label="是否显示" width="100">
        <template #default="scope">
          <el-tag v-if="String(scope.row.visible) === '0'" type="success"
            >显示</el-tag
          >
          <el-tag v-else type="danger">隐藏</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="240" fixed="right">
        <template #default="scope">
          <div class="flex space-x-2">
            <el-button
              v-if="scope.row.menuType !== 'O'"
              type="primary"
              size="small"
              plain
              @click="handleAddChild(scope.row)"
            >
              新增
            </el-button>
            <el-button
              v-else
              type="primary"
              size="small"
              plain
              disabled
              title="只有目录类型可以添加子菜单"
            >
              新增
            </el-button>
            <el-button
              type="warning"
              size="small"
              plain
              @click="handleEdit(scope.row)"
            >
              修改
            </el-button>
            <el-button
              type="danger"
              size="small"
              plain
              @click="handleDelete(scope.row)"
            >
              删除
            </el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>

    <!-- 菜单添加/编辑抽屉 -->
    <el-drawer
      v-model="drawerVisible"
      :title="dialogTitle"
      :direction="direction"
      size="380px"
      :destroy-on-close="true"
      :close-on-click-modal="false"
    >
      <el-form
        ref="menuFormRef"
        :model="menuForm"
        :rules="menuFormRules"
        label-width="100px"
        @keyup.enter.native="submitForm"
      >
        <el-form-item label="菜单类型" prop="menuType">
          <el-radio-group v-model="menuForm.menuType">
            <el-radio value="M">目录</el-radio>
            <el-radio value="F">菜单</el-radio>
            <el-radio value="O">接口</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="上级菜单" prop="parentId">
          <el-tree-select
            v-model="menuForm.parentId"
            :data="menuOptions"
            :props="{ label: 'menuName', value: 'id', children: 'children' }"
            placeholder="请选择上级菜单"
            style="width: 100%"
            clearable
          />
        </el-form-item>
        <el-form-item label="菜单名称" prop="menuName">
          <el-input
            v-model="menuForm.menuName"
            placeholder="请输入菜单名称"
            @keyup.enter="submitForm"
          />
        </el-form-item>
        <el-form-item label="菜单标识" prop="menuCode" v-if="!isEdit">
          <el-input
            v-model="menuForm.menuCode"
            placeholder="请输入菜单标识"
            @keyup.enter="submitForm"
          />
        </el-form-item>

        <el-form-item label="路由地址" prop="path">
          <el-input v-model="menuForm.path" placeholder="请输入路由地址" />
        </el-form-item>
        <el-form-item label="组件路径" prop="component">
          <el-input v-model="menuForm.component" placeholder="请输入组件路径" />
        </el-form-item>
        <el-form-item label="图标">
          <el-popover placement="bottom" width="450" trigger="click">
            <template #reference>
              <el-input
                v-model="menuForm.icon"
                placeholder="点击选择图标"
                readonly
              >
                <template #prefix>
                  <el-icon v-if="menuForm.icon"
                    ><component :is="menuForm.icon"
                  /></el-icon>
                </template>
              </el-input>
            </template>
            <div>
              <el-input
                v-model="iconSearchQuery"
                placeholder="搜索图标"
                clearable
                class="mb-1"
                size="small"
              >
                <template #prefix>
                  <el-icon><Search /></el-icon>
                </template>
              </el-input>

              <!-- 图标分类切换 -->
              <div class="icon-categories mb-1">
                <el-radio-group v-model="activeIconCategory" size="small">
                  <el-radio-button
                    v-for="category in iconCategories"
                    :key="category.key"
                    :value="category.key"
                  >
                    {{ category.label }}
                  </el-radio-button>
                </el-radio-group>
              </div>

              <div class="icon-grid">
                <div
                  v-for="icon in filteredIconList"
                  :key="icon.name"
                  class="icon-item"
                  :class="{ active: menuForm.icon === icon.name }"
                  @click="selectIcon(icon.name)"
                  :title="icon.name"
                >
                  <el-icon><component :is="icon.name" /></el-icon>
                  <div class="icon-name">{{ icon.name }}</div>
                </div>
              </div>

              <!-- 当前选中的图标 -->
              <div v-if="menuForm.icon" class="selected-icon">
                <div>当前选择：</div>
                <div class="icon-preview">
                  <el-icon><component :is="menuForm.icon" /></el-icon>
                  <span>{{ menuForm.icon }}</span>
                </div>
              </div>
            </div>
          </el-popover>
        </el-form-item>
        <el-form-item label="权限标识符">
          <el-input
            v-model="menuForm.permission"
            placeholder="请输入权限标识符"
          />
        </el-form-item>
        <el-form-item label="排序" prop="orderNum">
          <el-input-number v-model="menuForm.orderNum" :min="0" />
        </el-form-item>
        <el-form-item label="是否显示">
          <el-radio-group v-model="menuForm.visible">
            <el-radio :value="0">显示</el-radio>
            <el-radio :value="1">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="是否缓存">
          <el-radio-group v-model="menuForm.keepAlive">
            <el-radio :value="0">是</el-radio>
            <el-radio :value="1">否</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="是否认证">
          <el-radio-group v-model="menuForm.requiresAuth">
            <el-radio :value="0">是</el-radio>
            <el-radio :value="1">否</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="drawerVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm" ref="submitButton"
            >确定</el-button
          >
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Plus, Refresh } from '@element-plus/icons-vue'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { addmenu, getmenu, delmenu, updatamenu } from '@/api/menu.js'

// 查询参数
const queryParams = reactive({
  menuName: '',
})

// 表格数据
const tableData = ref([])
const loading = ref(false)
const menuOptions = ref([])
const addButton = ref(null)

// 抽屉相关
const drawerVisible = ref(false)
const dialogTitle = ref('添加菜单')
const direction = ref('rtl') // 从右向左打开
const isEdit = ref(false)
const menuFormRef = ref(null)
const menuForm = reactive({
  id: undefined,
  parentId: 0,
  menuName: '',
  menuCode: '',
  icon: '',
  menuType: 'M',
  orderNum: 0,
  path: '',
  component: '',
  visible: '0',
  keepAlive: '0',
  requiresAuth: '0',
  permission: '',
})
const submitButton = ref(null)

// 表单验证规则
const menuFormRules = {
  menuName: [
    { required: true, message: '请输入菜单名称', trigger: 'blur' },
    { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' },
  ],
  menuCode: [
    { required: true, message: '请输入菜单标识', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z0-9_]+$/,
      message: '菜单标识只能包含字母、数字和下划线',
      trigger: 'blur',
    },
  ],
  parentId: [{ required: true, message: '请选择上级菜单', trigger: 'change' }],
  menuType: [{ required: true, message: '请选择菜单类型', trigger: 'change' }],
  path: [{ required: true, message: '请输入路由地址', trigger: 'blur' }],
  component: [{ required: true, message: '请输入组件路径', trigger: 'blur' }],
  orderNum: [{ required: false, message: '请输入排序', trigger: 'blur' }],
}

// 图标相关
const iconList = ref([])
const iconSearchQuery = ref('')
const activeIconCategory = ref('all')
const iconCategories = [
  { key: 'all', label: '全部' },
  {
    key: 'common',
    label: '常用',
    icons: [
      'House',
      'User',
      'Setting',
      'Menu',
      'Document',
      'List',
      'Edit',
      'Delete',
      'Search',
      'Info',
      'Warning',
      'Plus',
      'Minus',
      'Check',
      'Close',
      'CircleCheck',
      'CircleClose',
      'Bell',
      'Message',
      'Notification',
      'Calendar',
      'Star',
    ],
  },
]

const filteredIconList = computed(() => {
  let result = iconList.value

  // 先按分类筛选
  if (activeIconCategory.value !== 'all') {
    const category = iconCategories.find(
      (c) => c.key === activeIconCategory.value
    )
    if (category && category.icons) {
      result = result.filter((icon) => category.icons.includes(icon.name))
    }
  }

  // 再按搜索筛选
  if (iconSearchQuery.value) {
    result = result.filter((icon) =>
      icon.name.toLowerCase().includes(iconSearchQuery.value.toLowerCase())
    )
  }

  return result
})

/**
 * 初始化图标列表
 */
const initIconList = () => {
  iconList.value = Object.keys(ElementPlusIconsVue).map((name) => ({
    name,
    component: ElementPlusIconsVue[name],
  }))
}

/**
 * 设置当前图标分类
 * @param {string} category - 分类键值
 */
const setIconCategory = (category) => {
  activeIconCategory.value = category
}

/**
 * 选择图标
 * @param {string} iconName - 图标名称
 */
const selectIcon = (iconName) => {
  menuForm.icon = iconName
}

// 获取菜单列表
const getMenuList = async () => {
  loading.value = true
  try {
    const { code, data, msg } = await getmenu(queryParams)
    if (code == 500) {
      throw new Error(msg)
    }
    tableData.value = data

    menuOptions.value = [
      {
        id: 0,
        menuName: '主目录',
        children: tableData.value
          ? JSON.parse(JSON.stringify(tableData.value))
          : [],
      },
    ]
  } catch (error) {
    ElMessage.error(error.message)
  } finally {
    loading.value = false
  }
}

// 处理搜索
const handleSearch = () => {
  getMenuList()
}

// 处理重置
const handleReset = () => {
  queryParams.menuName = ''
  getMenuList()
}

// 处理添加
const handleAdd = () => {
  resetForm()
  dialogTitle.value = '添加菜单'
  isEdit.value = false
  menuForm.parentId = 0
  drawerVisible.value = true
}

// 处理添加子菜单
const handleAddChild = (row) => {
  resetForm()
  dialogTitle.value = '添加菜单'
  isEdit.value = false
  menuForm.parentId = row.id
  drawerVisible.value = true
}

// 重置表单
const resetForm = () => {
  menuForm.id = undefined
  menuForm.parentId = 0
  menuForm.menuName = ''
  menuForm.menuCode = ''
  menuForm.icon = ''
  menuForm.menuType = 'M'
  menuForm.orderNum = 0
  menuForm.path = ''
  menuForm.component = ''
  menuForm.visible = 0
  menuForm.keepAlive = 0 // keepAlive 是否缓存
  menuForm.requiresAuth = 0 // requiresAuth 是否认证
  menuForm.permission = '' // permission 权限标识符
  // 延迟重置校验结果
  setTimeout(() => {
    menuFormRef.value?.resetFields()
  }, 0)
}

// 处理编辑
const handleEdit = (row) => {
  dialogTitle.value = '修改菜单'
  isEdit.value = true
  // 首先重置表单，避免上次编辑的数据残留
  resetForm()
  Object.assign(menuForm, row)

  drawerVisible.value = true
}

// 处理删除
const handleDelete = (row) => {
  ElMessageBox.confirm(`确定要删除菜单"${row.menuName}"吗？`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      const { code, msg } = await delmenu(row.id)
      if (code == 500) {
        throw new Error(msg)
      }
      // 这里应该调用删除API
      ElMessage.success('删除成功')
      getMenuList()
    })
    .catch((error) => {
      ElMessage.info("取消删除")
    })
}

// 处理提交表单
const submitForm = async () => {
  if (!menuFormRef.value) return

  await menuFormRef.value.validate(async (valid) => {
    if (valid) {
      try {
        if (isEdit.value) {
          // 调用更新菜单接口
          const { code, msg } = await updatamenu(menuForm)
          if (code === 500) {
            ElMessage.error(msg)
            return
          } else {
            ElMessage.success(isEdit.value ? '修改成功' : '添加成功')
          }
        } else {
          // 调用添加菜单接口
          const { code, msg } = await addmenu(menuForm)
          if (code === 500) {
            ElMessage.error(msg)
            return
          } else {
            ElMessage.success(isEdit.value ? '修改成功' : '添加成功')
          }
        }
      } catch (error) {
        ElMessage.error(error.message)
      } finally {
        drawerVisible.value = false
        getMenuList()
      }
    }
  })
}

onMounted(() => {
  getMenuList()
  initIconList()
})
</script>

<style lang="less" scoped>
.menu-manage {
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  .el-table {
    height: calc(100vh - 220px);
  }
}

.icon-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-height: 240px;
  overflow-y: auto;
  padding: 8px;
  margin-bottom: 8px;
}

.icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6px 3px;
  border: 1px solid #eee;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
  width: calc(16.666% - 7px);
  flex-shrink: 0;
  margin-bottom: 1px;

  @media (max-width: 500px) {
    width: calc(25% - 7px);
  }

  .el-icon {
    font-size: 18px;
    margin-bottom: 3px;
  }

  .icon-name {
    font-size: 9px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;
    text-align: center;
  }

  &:hover {
    background-color: #f5f7fa;
    color: #409eff;
    transform: translateY(-1px);
  }

  &.active {
    background-color: #ecf5ff;
    color: #409eff;
    border-color: #409eff;
  }
}

.icon-categories {
  display: flex;
  justify-content: center;
}

.selected-icon {
  display: flex;
  align-items: center;
  padding: 8px;
  margin-top: 4px;
  border-top: 1px solid #eee;

  .icon-preview {
    display: flex;
    align-items: center;
    margin-left: 8px;

    .el-icon {
      font-size: 16px;
      margin-right: 4px;
    }
  }
}
</style>
